package com.franklin.ideaplugin.maphelper.resolver.impl.collection;

import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.beans.colmember.PsiColMember;
import com.franklin.ideaplugin.maphelper.col.declaration.IColDeclaration;
import com.franklin.ideaplugin.maphelper.col.operation.ColOperationFactory;
import com.franklin.ideaplugin.maphelper.col.method.IColCreateMethod;
import com.franklin.ideaplugin.maphelper.col.method.IColInsertMethod;
import com.franklin.ideaplugin.maphelper.col.method.impl.ColInsertMethodImpl;
import com.franklin.ideaplugin.maphelper.utils.PsiColUtils;
import com.google.common.collect.Sets;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;

/**
 * 特殊方法调用
 *
 * @author Ye Junhui
 * @since 2024/3/12
 */
public class SpecialCollectionMethodCallExpressionResolver extends CollectionMethodCallExpressionColMemberResolver {

    public final static SpecialCollectionMethodCallExpressionResolver INSTANCE = new SpecialCollectionMethodCallExpressionResolver();

    /**
     * 自定义写入方法
     */
    private final static IColInsertMethod MY_METHOD = new ColInsertMethodImpl("add",1,0);

    @Override
    public boolean supports(IColDeclaration colDeclaration) {
        if (!super.supports(colDeclaration)){
            return false;
        }
        //操作
        IColCreateMethod colCreateMethod = getColCreateMethod(colDeclaration);

        return Objects.nonNull(colCreateMethod);
    }

    @Override
    public Collection<IColMember> resolveColMembers(PsiElement psiExpression, IColDeclaration colDeclaration) {
        //结果
        Set<IColMember> result = Sets.newLinkedHashSet();
        //寻找参数
        PsiExpressionList psiExpressionList = PsiTreeUtil.getChildOfType(psiExpression, PsiExpressionList.class);
        if (Objects.isNull(psiExpressionList)){
            return result;
        }
        IColCreateMethod colCreateMethod = getColCreateMethod(colDeclaration);
        if (Objects.isNull(colCreateMethod)){
            return result;
        }
        if (colCreateMethod.getParamCount() == -1){
            //可变形参
            processVars(psiExpressionList,result);
        }else {
            //传入集合
            processCollectionArg(psiExpressionList,result);
        }

        return result;
    }

    /**
     * 处理传入集合
     * @param psiExpressionList
     * @param result
     */
    private void processCollectionArg(PsiExpressionList psiExpressionList, Set<IColMember> result){
        CollectionMemberResolverFactory colMemberResolverFactory = getColMemberResolverFactory();
        Arrays.stream(psiExpressionList.getExpressions())
                .flatMap(childExpression -> {
                    IColDeclaration colDeclaration = PsiColUtils.findColExpressionDeclaration(childExpression);
                    Collection<IColMember> psiColMembers = colMemberResolverFactory.resolveExpression(childExpression, colDeclaration);
                    return psiColMembers.stream();
                })
                .forEach(result::add);
    }

    /**
     * 处理可变形参
     * @param psiExpressionList
     * @param result
     */
    private void processVars(PsiExpressionList psiExpressionList,Set<IColMember> result){
        Arrays.stream(psiExpressionList.getExpressions())
                .map(childExpression -> {
                    PsiColMember psiColMember = new PsiColMember();
                    psiColMember.setPsiExpressions(new PsiExpression[]{childExpression});
                    psiColMember.setColInsertMethod(MY_METHOD);
                    return psiColMember;
                })
                .forEach(result::add);
    }

    /**
     * 获取创建操作
     * @param colDeclaration
     * @return
     */
    private IColCreateMethod getColCreateMethod(IColDeclaration colDeclaration){
        return PsiColUtils.findColCreateMethod(colDeclaration,ColOperationFactory.COLLECTION_CREATE_OPERATIONS);
    }
}
